#include <math.h>
#include <windows.h>
#include <stdio.h>
#include "mysql\mysql.h"
#include "structs.h"
#include "CConsole.h"
#include "CDb.h"
#include "CNpc.h"
#include "CUtil.h"
#include "CZoneHandler.h"

float CUtil::distance(struct position A, struct position B){
	float one = 0, two = 0, three = 0, four = 0;

	one = A.x - B.x;
	two = A.y - B.y;
	three = A.z - B.z;
	one *= one;
	two *= two;
	three *= three;
	four = one + two + three;

	return (float)sqrt((double)four);
}

bool CUtil::withinDistance(float x1, float x2, float z1, float z2, struct position A){
	float tmp;
	
	if(x1 > x2){
		tmp = x1;
		x1 = x2;
		x2 = tmp;
	}
	if(z1 > z2){
		tmp = z1;
		z1 = z2;
		z2 = tmp;
	}
	return (bool)((x1 < A.x)&&(x2 > A.x)&&(z1 < A.z)&&(z2 > A.z));
}

bool CUtil::withinDistance(float x1, float x2, float y1, float y2, float z1, float z2, struct position A){
	float tmp;
	
	if(x1 > x2){
		tmp = x1;
		x1 = x2;
		x2 = tmp;
	}
	if(y1 > y2){
		tmp = y1;
		y1 = y2;
		y2 = tmp;
	}
	if(z1 > z2){
		tmp = z1;
		z1 = z2;
		z2 = tmp;
	}
	return (bool)((x1 < A.x)&&(x2 > A.x)&&(y1 < A.y)&&(y2 > A.y)&&(z1 < A.z)&&(z2 > A.z));
}

char * CUtil::trim(char * input){
	int i, start, end = 0;

	for(i = 0; input[i]; i++){
		if((input[i] >= 'a' && input[i] <= 'z') || (input[i] >= 'A' && input[i] <= 'Z') || (input[i] >= '0' && input[i] <= '9')){
			start = i;
			break;
		}
	}
	for(i = (int) strlen(input); i; i--){
		if((input[i] >= 'a' && input[i] <= 'z') || (input[i] >= 'A' && input[i] <= 'Z') || (input[i] >= '0' && input[i] <= '9')){
			end = i;
			break;
		}
	}
	if(end < start)
		end = start;
	for(i = start; i <= end; i++)
		input[i-start] = input[i];
	input[i-start] = 0;

	return input;
}

char * CUtil::my_strtok(char * input, char * delim){
	int len, i, j;

	len = (int) strlen(delim);
	for(i = 0; input[i]; i++){
		for(j = 0; j < len; j++){
			if(input[i] == delim[j]){
				input[i++] = 0;
				return input+i;
			}
		}
	}

	return 0;
}

char * CUtil::getINIstring(char * file, char * section, char * variable, char * output){
	FILE * fp;
	char * buf, * ptr, *ptr1, * ptr2, buf1[256];
	int size, i, j, k=2;

	fp = fopen(file, "r");
	if(!fp)
		return 0;
	fseek(fp, 0, SEEK_END);
	size = ftell(fp);
	if(!size){
		fclose(fp);
		return 0;
	}
	buf = (char *)malloc(size);
	if(!buf){
		fclose(fp);
		return 0;
	}
	rewind(fp);
	if(!fread(buf, sizeof(char), size, fp)){
		fclose(fp);
		free(buf);
		return 0;
	}
	fclose(fp);

	ptr = buf;
	while((ptr = my_strtok(ptr, "["))){
		if(!k--)
			break;
		ptr2 = strchr(ptr, ']');
		if(!ptr2){
			free(buf);
			return 0;
		}
		if(ptr+255 <= ptr2)
			continue;
		for(i = 0; ptr+i < ptr2; i++)
			buf1[i] = ptr[i];
		buf1[i] = 0;
		trim(buf1);
		if(strcmp(buf1, section))
			continue;
		ptr1 = strchr(++ptr2, '[');
		if(ptr1)
			*ptr1 = 0;
		for(i = 0, j = 0; ptr2[i]; i++){
			if(ptr2[i] == '\r' || ptr2[i] == '\n' || !ptr2[i] || ptr2[i] == EOF){
				j = i+1;
				continue;
			}
			if(ptr2[i] == '='){
				ptr2[i++] = 0;
				trim(ptr2+j);
				if(strcmp(ptr2+j, variable)){
					j = i;
					continue;
				}
				for(j = i; ptr2[j] != '\r' && ptr2[j] != '\n' && ptr2[j] != '\0' && ptr2[j] != EOF; j++);
				ptr2[j] = 0;
				trim(ptr2+i);
				strcpy(output, ptr2+i);
				free(buf);
				return output;
			}
		}
		break;
	}

	return 0;
}

int CUtil::getINIint(char * file, char * section, char * variable){
	char buf[256];

	if(!getINIstring(file, section, variable, buf))
		return 0;

	return atoi(buf);
}

float CUtil::getINIdouble(char * file, char * section, char * variable){
	char buf[256];

	if(!getINIstring(file, section, variable, buf))
		return 0;

	return (float)atof(buf);
}

float CUtil::calcAngle( float Position1X, float Position1Y, float Position2X, float Position2Y )
{
	float dx = Position2X-Position1X;
 	float dy = Position2Y-Position1Y;
	double angle=0.0f;
	// Calculate angle
 	if (dx == 0.0)
	{
		if (dy == 0.0)
			angle = 0.0;
		else if (dy > 0.0)
 			angle = M_PI * 0.5 /* / 2 */;
 		else
			angle = M_PI * 3.0 * 0.5/* / 2 */;
 	}
 	else if (dy == 0.0)
 	{
 		if (dx > 0.0)
			angle = 0.0;
		else
 			angle = M_PI;
	}
	else
	{
 		if (dx < 0.0)
 			angle = atanf(dy/dx) + M_PI;
		else if (dy < 0.0)
			angle = atanf(dy/dx) + (2*M_PI);
		else
 			angle = atanf(dy/dx);
 	}
 	// Convert to degrees
 	angle = angle * float(180 / M_PI);
 	// Return
	return float(angle);
 }

double CUtil::round(double x) {
	return ((x - floor(x)) >= 0.5) ? ceil(x) : floor(x);
}


char * CUtil::getJobString(int jobId){

	switch(jobId) {
		case 0x01:
			return "war";
	    case 0x02:
			return "mnk";
		case 0x03:
			return "whm";
		case 0x04:
			return "blm";
		case 0x05:
			return "rdm";
		case 0x06:
			return "thf";
		case 0x07:
			return "pld";
		case 0x08:
			return "drk";
		case 0x09:
			return "bst";
		case 0x0a:
			return "brd";
		case 0x0b:
			return "rng";
		case 0x0c:
			return "sam";
		case 0x0d:
			return "nin";
		case 0x0e:
			return "drg";
		case 0x0f:
			return "smn";
		case 0x10:
			return "blu";
		case 0x11:
			return "cor";
		case 0x12:
			return "pup";
		case 0x13:
			return "dnc";
		case 0x14:
			return "sch";
		default:
			return "notfound";
	}


}

const char * CUtil::getZoneName(unsigned short zone) {

	const char *ZONE_NAMES[] = {
    "unknown",
    "Phanauet_Channel",
    "Carpenters_Landing",
    "Manaclipper",
    "Bibiki_Bay",
    "Uleguerand_Range",
    "Bearclaw_Pinnacle",
    "Attohwa_Chasm",
    "Boneyard_Gully",
    "PsoXja",
    "The_Shrouded_Maw",
    "Oldton_Movalpolos",
    "Newton_Movalpolos",
    "MineShaft_#2716",
    "Hall_of_Transference",
    "none",
    "Promyvion_Holla",
    "Spire_of_Holla",
    "Promyvion_Dem",
    "Spire_of_Dem",
    "Promyvion_Mea",
    "Spire_of_Mea",
    "Promyvion_Vahzl",
    "Spire_of_Vahzl",
    "Lufaise_Meadows",
    "Misareaux_Coast",
    "Tavnazian_Safehold",
    "Phomiuna_Aqueducts",
    "Sacrarium",
    "Riverne_Site_#B01",
    "Riverne_Site_#A01",
    "Monarch_Linn",
    "Sealions_Den",
    "AlTaieu",
    "Grand_Palace_of_HuXzoi",
    "The_Garden_of_RuHmet",
    "Empyreal_Paradox",
    "Temenos",
    "Apollyon",
    "Dynamis_Valkurm",
    "Dynamis_Buburimu",
    "Dynamis_Qufim",
    "Dynamis_Tavnazia",
    "Diorama_Abdhaljs_Ghelsba",
    "Abdhaljs_Isle_Purgonorgo",
    "none",
    "Open_sea_route_to_Al_Zahbi",
    "Open_sea_route_to_Mhaura",
    "Al_Zahbi",
    "none",
    "Aht_Urhgan_Whitegate",
    "Wajaom_Woodlands",
    "Bhaflau_Thickets",
    "Nashmau",
    "Arrapago_Reef",
    "Ilrusi_Atoll",
    "Periqia",
    "Talacca_Cove",
    "Silver_Sea_route_to_Nashmau",
    "Silver_Sea_route_to_Al_Zahbi",
    "The_Ashu_Talif",
    "Mount_Zhayolm",
    "Halvung",
    "Lebros_Cavern",
    "Navukgo_Execution_Chamber",
    "Mamook",
    "Mamool_Ja_Training_Grounds",
    "Jade_Sepulcher",
    "Aydeewa_Subterrane",
    "Leujaoam_Sanctum",
    "Chocobo_Circuit",
    "The_Colosseum",
    "Alzadaal_Undersea_Ruins",
    "Zhayolm_Remnants",
    "Arrapago_Remnants",
    "Bhaflau_Remnants",
    "Silver_Sea_Remnants",
    "Nyzul_Isle",
    "Hazhalm_Testing_Grounds",
    "Caedarva_Mire",
    "Southern_San_d'Oria_[S]",
    "East_Ronfaure_[S]",
    "Jugner_Forest_[S]",
    "Vunkerl_Inlet_[S]",
    "Batallia_Downs_[S]",
    "La_Vaule_[S]",
    "Everbloom_Hollow",
    "Bastok_Markets_[S]",
    "North_Gustaberg_[S]",
    "Grauberg_[S]",
    "Pashhow_Marshlands_[S]",
    "Rolanberry_Fields_[S]",
	"Beadeaux_[S]",
    "Ruhotz_Silvermines",
    "Windurst_Waters_[S]",
    "West_Sarutabaruta_[S]",
    "Fort_Karugo-Narugo_[S]",
    "Meriphataud_Mountains_[S]",
    "Sauromugue_Champaign_[S]",
    "Oztroja_Castle_[S]",
    "West_Ronfaure",
    "East_Ronfaure",
    "La_Theine_Plateau",
    "Valkurm_Dunes",
    "Jugner_Forest",
    "Batallia_Downs",
    "North_Gustaberg",
    "South_Gustaberg",
    "Konschtat_Highlands",
    "Pashhow",
    "Rolanberry_Fields",
    "Beaucedine_Glacier",
    "Xarcabard",
    "Cape_Teriggan",
    "Eastern_Altepa_Desert",
    "West_Sarutabaruta",
    "East_Sarutabaruta",
    "Tahrongi_Canyon",
    "Buburimu_Peninsula",
    "Meriphataud_Mountains",
    "Sauromugue_Champaign",
    "The_Sanctuary_of_ZiTah",
    "RoMaeve",
    "Yuhtunga_Jungle",
    "Yhoator_Jungle",
    "Western_Altepa_Desert",
    "Qufim_Island",
    "Behemoths_Dominion",
    "Valley_of_Sorrows",
    "Ghoyu's_Reverie",
    "RuAun_Gardens",
    "Mordion_Gaol",
    "unknown",
    "unknown",
    "Dynamis_Beaucedine",
    "Dynamis_Xarcabard",
    "Beaucedine_Glacier_[S]",
    "Xarcabard_[S]",
    "Castle_Zvahl_Baileys_[S]",
    "Horlais_Peak",
    "Ghelsba_Outpost",
    "Fort_Ghelsba",
    "Yughott_Grotto",
    "Palborough_Mines",
    "Waughroon_Shrine",
    "Giddeus",
    "Balgas_Dais",
    "Beadeaux",
    "Qulun_Dome",
    "Davoi",
    "Monastic_Cavern",
    "Castle_Oztroja",
    "Altar_Room",
    "The_Boyahda_Tree",
    "Dragons_Aery",
    "Castle_Zvahl_Keep_[S]",
    "Throne_Room_[S]",
    "Middle_Delkfutts_Tower",
    "Upper_Delkfutts_Tower",
    "Temple_of_Uggalepih",
    "Den_of_Rancor",
    "Castle_Zvahl_Baileys",
    "Castle_Zvahl_Keep",
    "Sacrificial_Chamber",
    "Garlaige_Citadel_[S]",
    "Throne_Room",
    "Ranguemont_Pass",
    "Bostaunieux_Oubliette",
    "Chamber_of_Oracles",
    "Toraimarai_Canal",
    "Full_Moon_Fountain",
    "Crawlers'_Nest_[S]",
    "Zeruhn_Mines",
    "Korroloka_Tunnel",
    "Kuftal_Tunnel",
    "The_Eldieme_Necropolis_[S]",
    "Sea_Serpent_Grotto",
    "VeLugannon_Palace",
    "The_Shrine_of_RuAvitau",
    "Stellar_Fulcrum",
    "LaLoff_Amphitheater",
    "The_Celestial_Nexus",
    "Walk_of_Echos",
    "The_Last_Stand",
    "Lower_Delkfutts_Tower",
    "Dynamis_San_dOria",
    "Dynamis_Bastok",
    "Dynamis_Windurst",
    "Dynamis_Jeuno",
    "unknown",
    "King_Ranperres_Tomb",
    "Dangruf_Wadi",
    "Inner_Horutoto_Ruins",
    "Ordelles_Caves",
    "Outer_Horutoto_Ruins",
    "The_Eldieme_Necropolis",
    "Gusgen_Mines",
    "Crawlers_Nest",
    "Maze_of_Shakhrami",
    "unknown",
    "Garlaige_Citadel",
    "Cloister_of_Gales",
    "Cloister_of_Storms",
    "Cloister_of_Frost",
    "FeiYin",
    "Ifrits_Cauldron",
    "QuBia_Arena",
    "Cloister_of_Flames",
    "Quicksand_Caves",
    "Cloister_of_Tremors",
    "unknown",
    "Cloister_of_Tides",
    "Gustav_Tunnel",
    "Labyrinth_of_Onzozo",
    "Al_Zahbi_Residential_Area",
    "Jeuno_Residential_Area",
    "San_dOria_Residential_Area",
    "Bastok_Residential_Area",
    "Windurst_Residential_Area",
    "unknown",
    "Ship_bound_for_Selbina",
    "Ship_bound_for_Mhaura",
    "test_zone",
    "San_dOria_Jeuno_Airship",
    "Bastok_Jeuno_Airship",
    "Windurst_Jeuno_Airship",
    "Kazham_Jeuno_Airship",
    "Ship_bound_for_Selbina_Pirate",
    "Ship_bound_for_Mhaura_Pirate",
    "unknown",
    "Southern_San_dOria",
    "Northern_San_dOria",
    "Port_San_dOria",
    "Chateau_dOraguille",
    "Bastok_Mines",
    "Bastok_Markets",
    "Port_Bastok",
    "Bastok_Metalworks",
    "Windurst_Waters",
    "Windurst_Walls",
    "Port_Windurst",
    "Windurst_Woods",
    "Heavens_Tower",
    "RuLude_Gardens",
    "Upper_Jeuno",
    "Lower_Jeuno",
    "Port_Jeuno",
    "Rabao",
    "Selbina",
    "Mhaura",
    "Kazham",
    "Hall_of_the_Gods",
    "Norg",
    "San_dOria_Residential_Area",
    "Bastok_Residential_Area",
    "Windurst_Residential_Area",};

	return ZONE_NAMES[zone];

}

float CUtil::randFloat(float a, float b) {
	return ((b-a)*((float)rand()/RAND_MAX))+a;
}

void CUtil::exportZones(void) {
	char data[1024];
	unsigned short zoneCount = 0;
	unsigned short zoneID = 0;
	FILE* outputFile;

	for (zoneID = 0; zoneID < 256; zoneID++){
		zoneCount = (unsigned short)CZoneHandler::getInstance()->npcZoneList[zoneID].size() + (unsigned short)CZoneHandler::getInstance()->mobZoneList[zoneID].size();
		memcpy((data+(zoneID * 4)),&zoneID,2);
		memcpy((data+((zoneID * 4) + 2)),&zoneCount,2);
	}

	outputFile=fopen("./zoneExport.dat","wb+");
	if (outputFile!=NULL)
	{
		fwrite(data,sizeof(char),1024,outputFile);
		//fwrite(&data[0x11],sizeof(char),data[0x10],outputFile);
		fclose(outputFile);
		outputFile=NULL;
	}
}

void CUtil::importZone(char * filename) {
	MYSQL* mysqlConn;
	int count;
	char query[4096];

	FILE * file;
	unsigned long size;
	char * buf;

	file = fopen(filename, "rb");
	if(!file) {
		CConsole::outDebOnly("File not found: %s",filename);
		return;
	}
	fseek(file, 0, SEEK_END);
	size = ftell(file);
	if(!size){
		fclose(file);
		return;
	}

	buf = new char[size];

	rewind(file);
	
	if(!fread(buf, sizeof(char), size, file)){
		fclose(file);
		return;
	}
	unsigned long byteCount = 0;
	char header[3];
	memcpy(&header, &buf[byteCount], 3);
	byteCount += 3;
	if(memcmp(header, "Mon", 3)) {
		CConsole::outDebOnly("File not FFXIMon dat file. Cancelling import.");
		return;
	}
	unsigned short npcCount = 0;
	unsigned char zone = 0;
	bool renameTable = false;
	int nonamecount = 0;
	int qmcount = 1;
	while(byteCount < size) {
		char datName[24];
		memcpy(&datName, &buf[byteCount], 24);
		byteCount += 24;
		// each packet max size is 0xFF * 2
		char packet[512];
		memset(packet, 0, 512);
		unsigned short packetSize = buf[byteCount+1]*2;
		memcpy(&packet, &buf[byteCount], packetSize);

		CNpc npc;
		memcpy(&npc.m_id, &buf[byteCount+0x04], 4);
		unsigned int targID = 0;
		memcpy(&targID, &buf[byteCount+0x08], 2);
		npc.setTargId(targID);
		npc.type = buf[byteCount+0x0A];
		npc.loc.p.rotation = 0;
		memcpy(&npc.loc.p.rotation, &buf[byteCount+0x0B], 1);
		memcpy(&npc.loc.p.x, &buf[byteCount+0x0C], 4);
		memcpy(&npc.loc.p.y, &buf[byteCount+0x10], 4);
		memcpy(&npc.loc.p.z, &buf[byteCount+0x14], 4);
		memcpy(&npc.flag, &buf[byteCount+0x18], 4);
		npc.m_speed = buf[byteCount+0x1C];
		npc.m_speedAlt = buf[byteCount+0x1D];
		//Dont need HPP, byte 0x1E
		npc.h.animation = buf[byteCount+0x1F];
		npc.status = buf[byteCount+0x20];
		npc.unknown = 0;
		memcpy(&npc.unknown, &buf[byteCount+0x21], 3);
		npc.m_namePrefix = buf[byteCount+0x27];
		npc.m_animationAlt = buf[byteCount+0x2A];
		npc.namevis = buf[byteCount+0x2B];

		if(npc.type & 0x10) {
			memcpy(&npc.lookc, &buf[byteCount+0x30], 20);
			memcpy(&npc.m_name, datName, 16);
		} else {
			memcpy(&npc.look, &buf[byteCount+0x30], 4);
			memcpy(&npc.m_name, &buf[byteCount+0x34], 16);
		}
		for(unsigned char i = 0; i < 16; i++)
			if(npc.m_name[i] == 0x27) // ' char
				npc.m_name[i] = 0x5F; // replace with _ char
		npcCount ++;

		// give unnamed npcs a dummy name
		if(npc.m_name[0] == 0 && npc.m_name[1] == 0) {
			sprintf(npc.m_name,"no_name_%i",nonamecount++);
		}

		// change ??? names to qm1 - qmN
		if(!strcmp("???",npc.m_name)) {
			sprintf(npc.m_name,"qm%i",qmcount++);
		}

		zone = (unsigned char)(npc.m_id >> 12);
	

		memset(query,0,4096);
		sprintf(query, "DELETE FROM npc_list WHERE id = %i",npc.m_id);
		count = (int) strlen(query);
		mysqlConn=CDb::getConn(); //get conn
		mysql_real_query(mysqlConn, query, count);
		CDb::pushConn(mysqlConn); //release conn

		if(npc.status != 1 && npc.status != 7) {
				CConsole::outDebOnly("NPC #%3i: Name: %s, Zone 0x%2hx, mainID %i, targID %i", npcCount, npc.m_name, zone, npc.m_id, npc.getTargId());
			memset(query,0,4096);
			sprintf(query, "INSERT INTO `npc_list` (id, name, targid, type, pos_rot, pos_x, pos_y, pos_z, ", CUtil::getZoneName(zone));
			sprintf(query, "%s flag, speed, alt_speed, animation, alt_animation, namevis, status, ", query);
			sprintf(query, "%s unknown, look, name_prefix, zone) VALUES (%i,'%s',%i,%i,%i,%.3f,%.3f,%.3f,%i,%i,%i,%i,%i,%i,%i,%i,'", query,
				npc.m_id, npc.m_name, npc.getTargId(), npc.type, npc.loc.p.rotation, npc.loc.p.x, npc.loc.p.y, npc.loc.p.z, npc.flag, npc.m_speed, npc.m_speedAlt, 
				npc.h.animation, npc.m_animationAlt, npc.namevis, npc.status, npc.unknown);
			count = (int) strlen(query);
			if(npc.type & 0x10) {
				mysql_real_escape_string(mysqlConn, query+count, (char *)&(npc.lookc), sizeof(npc.lookc));
			} else {
				mysql_real_escape_string(mysqlConn, query+count, (char *)&(npc.look), sizeof(npc.look));
			}
			sprintf(query, "%s',%i,%i)", query, npc.m_namePrefix, zone);
			count = (int) strlen(query);
			mysqlConn=CDb::getConn(); //get conn
			mysql_real_query(mysqlConn, query, count);
			CDb::pushConn(mysqlConn); //release conn
			memset(query,0,4096);
		}

		byteCount += packetSize;
	}
	fclose(file);
	delete buf;
	CZoneHandler::getInstance()->loadZoneList(zone);
}

void CUtil::groupNewTable() {

	MYSQL* mysqlConn;
	int count;
	char query[4096];

	MYSQL_RES * res;
	MYSQL_ROW row;

	strcpy(query, "SELECT * FROM `pool_mobs` GROUP BY name ");

	count = (int) strlen(query);

	mysqlConn=CDb::getConn(); //get conn
	mysql_real_query(mysqlConn, query, count);

	res = mysql_store_result(mysqlConn);
	CDb::pushConn(mysqlConn); //release conn


	if(!res)
	{
	//	CConsole::outErr("Zone 0x%X\t -> %s not found in DB!",zone ,CUtil::getZoneName(zone));
		//return 0;
	}else if(!mysql_num_rows(res)){
		mysql_free_result(res);
		//return size;
	} else {
		int npccnt = 0;
		int mobcnt = 0;
		int look = 0;
		char lookc[20];
		unsigned char newName[30];
		while((row = mysql_fetch_row(res))){
				unsigned long *lengths = mysql_fetch_lengths(res);
				memset(lookc,0,20);
			
				memcpy(lookc, row[5], 20);
			

				CConsole::outTime("%s",row[1]);
				memset(query,0,4096);
				memset(newName,0,30);
				memcpy(newName, row[1], lengths[1]);
				sprintf(query, "INSERT INTO `pool_mobs2` (`poolid`, `name`, `familyid`, `name_prefix`,`flag`,`unknown`, `modelid`) VALUES (NULL,'%s',%i,%i,%i,%i,'", newName , atoi(row[3]) ,atoi(row[6]),atoi(row[7]),atoi(row[8]));
				count = (int) strlen(query);
				count += mysql_real_escape_string(mysqlConn, query+count, lookc, 20);			
				strcpy(query+count, "')");
				count += 2;
				mysqlConn=CDb::getConn(); //get conn
				mysql_real_query(mysqlConn, query, count);
				CDb::pushConn(mysqlConn); //release conn
			
		}
		mysql_free_result(res);
	}


}

void CUtil::fillNewTable(unsigned short zone) {
	MYSQL* mysqlConn;
	int count;
	char query[4096];

	MYSQL_RES * res;
	MYSQL_ROW row;

		//load NPCs and MOBs
	strcpy(query, "SELECT * FROM mob GROUP BY mobid" );

	count = (int) strlen(query);

	mysqlConn=CDb::getConn(); //get conn
	mysql_real_query(mysqlConn, query, count);

	res = mysql_store_result(mysqlConn);
	CDb::pushConn(mysqlConn); //release conn
	char lookc[21];
	char newName[30];

		while((row = mysql_fetch_row(res))){
			CConsole::outTime("%s",row[1]);
			unsigned long *lengths = mysql_fetch_lengths(res);
			memset(lookc,0,20);
		

			//	CConsole::outTime("%s",row[0]);
			memset(query,0,4096);
			memset(newName,0,30);
			memcpy(newName, row[1], lengths[1]);
			memcpy(lookc,row[3],20);
			sprintf(query, "INSERT INTO `pool_mobs` (`poolid`, `name`, `zoneid`, `family`, `system`, `name_prefix`,`flag`,`unknown`,`modelid`) VALUES (NULL,'%s',%i,%i,%i,%i,%i,%i,'", newName , atoi(row[2]), atoi(row[4]), 0, 0, 0, 0);
			count = (int) strlen(query);
			count += mysql_real_escape_string(mysqlConn, query+count, lookc, 20);			
			strcpy(query+count, "')");
			count += 2;
			mysqlConn=CDb::getConn(); //get conn
			mysql_real_query(mysqlConn, query, count);
			CDb::pushConn(mysqlConn); //release conn
		
			
		}
		mysql_free_result(res);
}

void CUtil::buildIdPool() {
	MYSQL* mysqlConn;
	int count;
	char query[4096];

	MYSQL_RES * res;
	MYSQL_ROW row;

	memset(query,0,4096);

	strcpy(query, "SELECT poolid,name FROM pool_mobs2");



	count = (int) strlen(query);

	mysqlConn=CDb::getConn(); //get conn
	mysql_real_query(mysqlConn, query, count);

	res = mysql_store_result(mysqlConn);
	CDb::pushConn(mysqlConn); //release conn


	if(!res)
	{
	//	CConsole::outErr("Zone 0x%X\t -> %s not found in DB!",zone ,CUtil::getZoneName(zone));
		//return 0;
	}else if(!mysql_num_rows(res)){
		mysql_free_result(res);
		//return size;
	} else {
		int npccnt = 0;
		int mobcnt = 0;
		int look = 0;

		while((row = mysql_fetch_row(res))){


			
					memset(query,0,4096);
					CConsole::outTime("%i , %s", atoi(row[0]),row[1] );
						memset(query,0,4096);
						sprintf(query, "UPDATE `pool_mobids` SET poolid = %i WHERE name = '%s'", atoi(row[0]),row[1]);
					count = (int) strlen(query);
					mysqlConn=CDb::getConn(); //get conn
					mysql_real_query(mysqlConn, query, count);
					CDb::pushConn(mysqlConn); //release conn


		}

		mysql_free_result(res);
		
	}

}

/*void CUtil::updateAnimIds() {
	MYSQL* mysqlConn;
	int count;
	char query[4096];

	MYSQL_RES * res;
	MYSQL_ROW row;

	memset(query,0,4096);

	strcpy(query, "SELECT internalId ,animationId, realId FROM abilities");



	count = (int) strlen(query);

	mysqlConn=CDb::getConn(); //get conn
	mysql_real_query(mysqlConn, query, count);

	res = mysql_store_result(mysqlConn);
	CDb::pushConn(mysqlConn); //release conn


	if(!res)
	{
	//	CConsole::outErr("Zone 0x%X\t -> %s not found in DB!",zone ,CUtil::getZoneName(zone));
		//return 0;
	}else if(!mysql_num_rows(res)){
		mysql_free_result(res);
		//return size;
	} else {


		while((row = mysql_fetch_row(res))){


				unsigned short id = ((atoi(row[1]) << 1) | (atoi(row[1]) >> (16-1)));

				memset(query,0,4096);
				sprintf(query, "UPDATE `abilities` SET realId = %i WHERE internalId = %i", id ,atoi(row[0]));
				count = (int) strlen(query);
				mysqlConn=CDb::getConn(); //get conn
				mysql_real_query(mysqlConn, query, count);
				CDb::pushConn(mysqlConn); //release conn


		}

		mysql_free_result(res);
		
	}

}*/

void CUtil::updateAnimIds() {
	MYSQL* mysqlConn;
	int count;
	char query[4096];

	MYSQL_RES * res;
	MYSQL_ROW row;

	memset(query,0,4096);

	strcpy(query, "SELECT Name,Type FROM enemy_stat GROUP BY Name");



	count = (int) strlen(query);

	mysqlConn=CDb::getConn(); //get conn
	mysql_real_query(mysqlConn, query, count);

	res = mysql_store_result(mysqlConn);
	CDb::pushConn(mysqlConn); //release conn


	if(!res)
	{
	//	CConsole::outErr("Zone 0x%X\t -> %s not found in DB!",zone ,CUtil::getZoneName(zone));
		//return 0;
	}else if(!mysql_num_rows(res)){
		mysql_free_result(res);
		//return size;
	} else {


		while((row = mysql_fetch_row(res))){

				unsigned long *lengths = mysql_fetch_lengths(res);

				char name[30];
				memset(name, 0, 30);
				memcpy(name, row[0], lengths[0]);
				

				memset(query,0,4096);
				sprintf(query, "UPDATE pool_mobs2 SET mobType = %i WHERE name = '%s'", atoi(row[1]),row[0] );
				count = (int) strlen(query);
				mysqlConn=CDb::getConn(); //get conn
				mysql_real_query(mysqlConn, query, count);
				CDb::pushConn(mysqlConn); //release conn


		}

		mysql_free_result(res);
		
	}

}



char * CUtil::getWeaponSkillName(int skillid) {

	MYSQL* mysqlConn;
	int count;
	char query[4096];

	MYSQL_RES * res;
	MYSQL_ROW row;
	static char name[20];

	memset(query,0,4096);
	unsigned long * lengths;

	sprintf(query, "SELECT WeaponSkill FROM weaponskills WHERE ID = %i",skillid);



	count = (int) strlen(query);

	mysqlConn=CDb::getConn(); //get conn
	mysql_real_query(mysqlConn, query, count);

	res = mysql_store_result(mysqlConn);
	CDb::pushConn(mysqlConn); //release conn


	if(!res)
	{

	}else if(!mysql_num_rows(res)){
		mysql_free_result(res);
		//return size;
	} else {
		if((row = mysql_fetch_row(res))){
			lengths = mysql_fetch_lengths(res);

			memset(name,0,20);
			memcpy(name, row[0], lengths[0]);	

		}

		mysql_free_result(res);
		
	}

	return name;
}

#define ROTATE_LEFT = 1;
#define ROTATE_RIGHT = 2;


int calcmask(int bitstorotate, int direction) {
	int mask = 0;
	int c;
		
	if (bitstorotate == 0)
		return 0;
			
	c = 0x80000000;
	mask = (c >> bitstorotate);

	mask = (c >> (32 - bitstorotate));
	mask = ~mask;

		
	return mask;
}



int CUtil::rotateLeft(int number, int bits) {

		int tmprslt =0;
		int mask=0;;
		int target=0;
		
		bits %= 32;
		target = number;
		
		// determine which bits will be impacted by the rotate
		mask = calcmask(bits, 2);
		
		// save off the bits which will be impacted
		tmprslt = number & mask;

      		// perform the actual rotate right
		target = (number  >> bits);

      		// now rotate the saved off bits so they are in the proper place
		tmprslt <<= (32 - bits);

      		// now add the saved off bits
		target |= tmprslt;
		
		// and return the result
		return target;



}